using System;
using System.Reflection;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.PowerShell.CmdletManagement;

namespace CmdletDesignerTests
{
    /// <summary>
    /// Summary description for TestParameterDetails
    /// </summary>
    [TestClass]
    public class TestParameterDetails
    {
        public TestParameterDetails()
        {
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        // Ensure the class proxies all attributes
        [TestMethod]
        public void TestProxy()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", 
                new string[] { "Alias1", "Alias2" }, true, true, true, true, true, true, 
                new int[] { 1, 10 }, true, true, new int[] { 1, 10 }, new string[] { "Set1", "Set2" }, 
                new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1", "Custom2", "Custom3", 
                "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry3 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName2", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            
            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);
            parameters.Add(parameterSetEntry3);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure the ID is the same
            Assert.AreEqual(parameter.Id, group.Id);

            // Ensure the project is the same
            Assert.AreEqual(parameter.ProjectName, group.ProjectName);

            // Ensure the cmdlet is the same
            Assert.AreEqual(parameter.CmdletName, group.CmdletName);

            // Ensure the parameter name is the same
            Assert.AreEqual(parameter.Name, group.Name);

            // Ensure the type name is the same
            Assert.AreEqual(parameter.Type, group.Type);

            // Ensure the description is the same
            Assert.AreEqual(parameter.Description, group.Description);

            // Ensure the help description is the same
            Assert.AreEqual(parameter.HelpDescription, group.HelpDescription);

            // Ensure the default value is the same
            Assert.AreEqual(parameter.DefaultValue, group.DefaultValue);

            // Ensure the aliases are the same
            for(int counter = 0; counter < parameter.Alias.Length; counter++)
            {
                Assert.AreEqual(parameter.Alias[counter], group.Alias[counter]);
            }

            // Ensure that AllowGlobbing is equal
            Assert.AreEqual(parameter.AllowGlobbing, group.AllowGlobbing);

            // Ensure that AllowMultiple is equal
            Assert.AreEqual(parameter.AllowMultiple, group.AllowMultiple);
            
            // Ensure that AllowEmptyCollection is equal
            Assert.AreEqual(parameter.AllowEmptyCollection, group.AllowEmptyCollection);
            
            // Ensure that AllowEmptyString is equal
            Assert.AreEqual(parameter.AllowEmptyString, group.AllowEmptyString);
            
            // Ensure that AllowNull is equal
            Assert.AreEqual(parameter.AllowNull, group.AllowNull);
            
            // Ensure that ValidateCount is equal
            for (int counter = 0; counter < parameter.Alias.Length; counter++)
            {
                Assert.AreEqual(parameter.ValidateCount[counter], group.ValidateCount[counter]);
            }
            
            // Ensure that ValidateNotNull is equal
            Assert.AreEqual(parameter.ValidateNotNull, group.ValidateNotNull);
            
            // Ensure that ValidateNotNullOrEmpty is equal
            Assert.AreEqual(parameter.ValidateNotNullOrEmpty, group.ValidateNotNullOrEmpty);
            
            // Ensure that ValidateRange is equal
            for (int counter = 0; counter < parameter.Alias.Length; counter++)
            {
                Assert.AreEqual(parameter.ValidateRange[counter], group.ValidateRange[counter]);
            }
            
            // Ensure that ValidateSet is equal
            for (int counter = 0; counter < parameter.Alias.Length; counter++)
            {
                Assert.AreEqual(parameter.ValidateSet[counter], group.ValidateSet[counter]);
            }
            
            // Ensure that ValidateLength is equal
            for (int counter = 0; counter < parameter.Alias.Length; counter++)
            {
                Assert.AreEqual(parameter.ValidateLength[counter], group.ValidateLength[counter]);
            }

            // Ensure that ValidatePattern is equal
            Assert.AreEqual(parameter.ValidatePattern, group.ValidatePattern);

            // Ensure that Dynamic is equal
            Assert.AreEqual(parameter.IsDynamic, group.IsDynamic);

            // Ensure that Notes is equal
            Assert.AreEqual(parameter.Notes, group.Notes);

            // Ensure that Custom1 is equal
            Assert.AreEqual(parameter.Custom1, group.Custom1);

            // Ensure that Custom2 is equal
            Assert.AreEqual(parameter.Custom2, group.Custom2);

            // Ensure that Custom3 is equal
            Assert.AreEqual(parameter.Custom3, group.Custom3);

            // Ensure that Custom4 is equal
            Assert.AreEqual(parameter.Custom4, group.Custom4);

            // Ensure that Mandatory is equal
            Assert.AreEqual(parameterSetEntry.Mandatory, group.Mandatory);

            // Ensure that Position is equal
            Assert.AreEqual(parameterSetEntry.Position.ToString(), group.Position);

            // Ensure that ValueFromPipeline is equal
            Assert.AreEqual(parameterSetEntry.ValueFromPipeline, group.ValueFromPipeline);

            // Ensure that ValueFromPipelineByPropertyName is equal
            Assert.AreEqual(parameterSetEntry.ValueFromPipelineByPropertyName, group.ValueFromPipelineByPropertyName);

            // Ensure that ValueFromRemainingArguments is equal
            Assert.AreEqual(parameterSetEntry.ValueFromRemainingArguments, group.ValueFromRemainingArguments);

            // Ensure that HelpMessage is equal
            Assert.AreEqual(parameterSetEntry.HelpMessage, group.HelpMessage);

            // Ensure that HelpMessageBaseName is equal
            Assert.AreEqual(parameterSetEntry.HelpMessageBaseName, group.HelpMessageBaseName);

            // Ensure that HelpMessageResourceId is equal
            Assert.AreEqual(parameterSetEntry.HelpMessageResourceId, group.HelpMessageResourceId);
        }

        // Ensure the class supports varying position
        [TestMethod]
        public void TestVaryByPosition()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 1, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry3 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName2", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);
            parameters.Add(parameterSetEntry3);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure that Position changes
            Assert.AreEqual(PsSpecCmdletParameterDetails.Constants.VariesByParameterSet, group.Position);
        }

        // Ensure the class supports varying by pipeline
        [TestMethod]
        public void TestVaryByPipeline()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, false,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry3 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName2", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);
            parameters.Add(parameterSetEntry3);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure that VFP changes
            Assert.AreEqual(null, group.ValueFromPipeline);
        }

        // Ensure the class supports varying by pipeline by property name
        [TestMethod]
        public void TestVaryByPipelineByPropertyName()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                false, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry3 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName2", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);
            parameters.Add(parameterSetEntry3);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure that VFPBPN changes
            Assert.AreEqual(null, group.ValueFromPipelineByPropertyName);
        }

        // Ensure the class supports varying by pipeline by remaining arguments
        [TestMethod]
        public void TestVaryByPipelineByRemainingArgs()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, false, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry3 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName2", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);
            parameters.Add(parameterSetEntry3);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure that VFRA changes
            Assert.AreEqual(null, group.ValueFromRemainingArguments);
        }

        // Ensure the class supports varying by help message
        [TestMethod]
        public void TestVaryByHelpMessage()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage2", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry3 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName2", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);
            parameters.Add(parameterSetEntry3);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure that helpmessage changes
            Assert.AreEqual(PsSpecCmdletParameterDetails.Constants.VariesByParameterSet, group.HelpMessage);
        }

        // Ensure the class supports varying by help message basename
        [TestMethod]
        public void TestVaryByHelpMessageBaseName()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName2", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry3 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName2", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);
            parameters.Add(parameterSetEntry3);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure that helpmessagebasename changes
            Assert.AreEqual(PsSpecCmdletParameterDetails.Constants.VariesByParameterSet, group.HelpMessageBaseName);
        }

        // Ensure the class supports varying by help message resource id
        [TestMethod]
        public void TestVaryByHelpMessageResourceId()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId2", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry3 = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName2", "ParameterName2", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);
            parameters.Add(parameterSetEntry3);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure that helpmessageresourceid changes
            Assert.AreEqual(PsSpecCmdletParameterDetails.Constants.VariesByParameterSet, group.HelpMessageResourceId);
        }

        // Ensure the defaults come out properly
        [TestMethod]
        public void TestDefaults()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", null, null, false,
                false, false, false, false, false, null, false, false, null, null,
                null, null, null, null, null, null, null, null, null);
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, null, "ParameterName", "CmdletName", "ProjectName", false, null, false,
                false, false, null, null, null, -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure the project is the same
            Assert.AreEqual(parameter.ProjectName, group.ProjectName);

            // Ensure the cmdlet is the same
            Assert.AreEqual(parameter.CmdletName, group.CmdletName);

            // Ensure the parameter name is the same
            Assert.AreEqual(parameter.Name, group.Name);

            // Ensure the type name is the same
            Assert.AreEqual(parameter.Type, group.Type);

            // Ensure the description is the same
            Assert.AreEqual(null, group.Description);

            // Ensure the aliases are of zero length
            Assert.AreEqual(null, group.Alias);

            // Ensure that AllowGlobbing is equal
            Assert.AreEqual(false, group.AllowGlobbing);

            // Ensure that AllowMultiple is equal
            Assert.AreEqual(false, group.AllowMultiple);

            // Ensure that Dynamic is equal
            Assert.AreEqual(false, group.IsDynamic);

            // Ensure that AllowEmptyCollection is equal
            Assert.AreEqual(false, group.AllowEmptyCollection);

            // Ensure that AllowEmptyString is equal
            Assert.AreEqual(false, group.AllowEmptyString);

            // Ensure that AllowNull is equal
            Assert.AreEqual(false, group.AllowNull);

            // Ensure that ValidateCount is equal
            Assert.AreEqual(null, group.ValidateCount);

            // Ensure that ValidateNotNull is equal
            Assert.AreEqual(false, group.ValidateNotNull);

            // Ensure that ValidateNotNullOrEmpty is equal
            Assert.AreEqual(false, group.ValidateNotNullOrEmpty);

            // Ensure that ValidateRange is equal
            Assert.AreEqual(null, group.ValidateRange);

            // Ensure that ValidateSet is equal
            Assert.AreEqual(null, group.ValidateSet);

            // Ensure that ValidateLength is equal
            Assert.AreEqual(null, group.ValidateLength);

            // Ensure that ValidatePattern is equal
            Assert.AreEqual(null, group.ValidatePattern);

            // Ensure that Notes is equal
            Assert.AreEqual(null, group.Notes);

            // Ensure that Mandatory is equal
            Assert.AreEqual(false, group.Mandatory);

            // Ensure that Position is equal
            Assert.AreEqual("", group.Position);

            // Ensure that ValueFromPipeline is equal
            Assert.AreEqual(false, group.ValueFromPipeline);

            // Ensure that ValueFromPipelineByPropertyName is equal
            Assert.AreEqual(false, group.ValueFromPipelineByPropertyName);

            // Ensure that ValueFromRemainingArguments is equal
            Assert.AreEqual(false, group.ValueFromRemainingArguments);

            // Ensure that HelpMessage is equal
            Assert.AreEqual(null, group.HelpMessage);

            // Ensure that HelpMessageBaseName is equal
            Assert.AreEqual(null, group.HelpMessageBaseName);

            // Ensure that HelpMessageResourceId is equal
            Assert.AreEqual(null, group.HelpMessageResourceId);
        }

        // Should be able to update something to its default
        [TestMethod]
        public void UpdateToDefault()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId2", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // Ensure that mandatory is unpecified
            Assert.AreEqual(null, group.Mandatory);

            group.Mandatory = false;
            
            // Ensure that mandatory has been changed
            Assert.AreEqual(false, group.Mandatory);
        }

        // Test the parameter set bubble-up
        [TestMethod]
        public void TestParameterSetBubbleUp()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId2", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            string[] expectedParameterSets = new string[] { "ParameterSetName", "ParameterSetName2" };

            // Test that bubble-up of parameter set name works
            for (int counter = 0; counter < expectedParameterSets.Length; counter++)
            {
                Assert.AreEqual(expectedParameterSets[counter], group.ParameterSets[counter]);
            }
        }

        // Remove a parameter from a parameter set
        [TestMethod]
        public void TestParameterSetRemove()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId2", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);
            
            // This parameter set has a conflict
            Assert.AreEqual(null, group.Mandatory);

            string[] newParameterSets = new string[] { "ParameterSetName" };
            Assert.AreEqual(2, group.ParameterSets.Count);

            group.ParameterSets = new List<string>(newParameterSets);

            Assert.AreEqual(1, group.ParameterSets.Count);

            // This parameter set should no longer have a conflict
            Assert.AreEqual(true, group.Mandatory);

            // Test that bubble-up of parameter set name works
            for (int counter = 0; counter < newParameterSets.Length; counter++)
            {
                Assert.AreEqual(newParameterSets[counter], group.ParameterSets[counter]);
            }
        }

        // Remove a parameter from a parameter set, then add it back
        [TestMethod]
        public void TestParameterSetRemoveThenAdd()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId2", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // This parameter set has a conflict
            Assert.AreEqual(null, group.Mandatory);

            string[] newParameterSets = new string[] { "ParameterSetName" };
            Assert.AreEqual(2, group.ParameterSets.Count);

            group.ParameterSets = new List<string>(newParameterSets); ;

            Assert.AreEqual(1, group.ParameterSets.Count);

            // This parameter set should no longer have a conflict
            Assert.AreEqual(true, group.Mandatory);

            // Test that bubble-up of parameter set name works
            for (int counter = 0; counter < newParameterSets.Length; counter++)
            {
                Assert.AreEqual(newParameterSets[counter], group.ParameterSets[counter]);
            }

            newParameterSets = new string[] { "ParameterSetName", "ParameterSetName2" };

            group.ParameterSets = new List<string>(newParameterSets);

            Assert.AreEqual(2, group.ParameterSets.Count);

            // This parameter set again has the conflict
            Assert.AreEqual(null, group.Mandatory);

            // Test that bubble-up of parameter set name works
            for (int counter = 0; counter < newParameterSets.Length; counter++)
            {
                Assert.AreEqual(newParameterSets[counter], group.ParameterSets[counter]);
            }
        }

        // Add a parameter to a parameter set, with no mixed items.
        // Should get all the defaults properly
        [TestMethod]
        public void TestParameterSetAddNoMixedItems()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // This parameter set does not have a conflict
            Assert.AreEqual(true, group.Mandatory);

            string[] newParameterSets = new string[] { "ParameterSetName", "ParameterSetName2" };
            Assert.AreEqual(1, group.ParameterSets.Count);

            group.ParameterSets = new List<string>(newParameterSets);
            
            Assert.AreEqual(2, group.ParameterSets.Count);

            // This parameter set should still not have a conflict
            Assert.AreEqual(true, group.Mandatory);
            
            // Test that bubble-up of parameter set name works
            for (int counter = 0; counter < newParameterSets.Length; counter++)
            {
                Assert.AreEqual(newParameterSets[counter], group.ParameterSets[counter]);
            }
        }

        // Add a parameter to a parameter set, with mixed items
        [TestMethod]
        public void TestParameterSetAddWithMixedItems()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);
            PsSpecCmdletParameterSetEntry parameterSetEntry2 = new PsSpecCmdletParameterSetEntry(
                121, "ParameterSetName2", "ParameterName", "CmdletName", "ProjectName", false, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId2", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);
            parameters.Add(parameterSetEntry2);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // This parameter set has a conflict
            Assert.AreEqual(null, group.Mandatory);
            Assert.AreEqual(2, group.ParameterSets.Count);

            string[] newParameterSets = new string[] { "ParameterSetName","ParameterSetName2", "ParameterSetName3" };
            group.ParameterSets = new List<string>(newParameterSets);

            Assert.AreEqual(3, group.ParameterSets.Count);

            // This parameter set should still have a conflict
            Assert.AreEqual(null, group.Mandatory);

            // Remove the first 2 parameter sets
            newParameterSets = new string[] { "ParameterSetName3" };
            group.ParameterSets = new List<string>(newParameterSets);
            Assert.AreEqual(1, group.ParameterSets.Count);

            // We should no longer have a conflict
            Assert.AreEqual(false, group.Mandatory);
        }

        // Change parameter set
        [TestMethod]
        public void TestParameterSetChange()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            // This parameter should be mandatory
            Assert.AreEqual(true, group.Mandatory);

            string[] newParameterSets = new string[] { null };
            group.ParameterSets = new List<string>(newParameterSets);

            Assert.AreEqual(1, group.ParameterSets.Count);

            // This parameter set should still be mandatory
            Assert.AreEqual(true, group.Mandatory);
        }

        // Test that it defines all parameters
        [TestMethod]
        public void TestParameterCoverage()
        {
            PsSpecCmdletParameter parameter = new PsSpecCmdletParameter(
                1, "ProjectName", "CmdletName", "ParameterName", "Type", "Description", new string[] { "Alias1", "Alias2" },
                true, true, true, true, true, true, new int[] { 1, 10 }, true, true, new int[] { 1, 10 },
                new string[] { "Set1", "Set2" }, new int[] { 2, 11 }, "a-z", "Notes", "Default", "Custom1",
                "Custom2", "Custom3", "Custom4", "HelpDescription");
            PsSpecCmdletParameterSetEntry parameterSetEntry = new PsSpecCmdletParameterSetEntry(
                123, "ParameterSetName", "ParameterName", "CmdletName", "ProjectName", true, 0, true,
                true, true, "HelpMessage", "HelpMessageBaseName", "HelpMessageResourceId", -1);

            List<PsSpecCmdletParameterSetEntry> parameters = new List<PsSpecCmdletParameterSetEntry>();
            parameters.Add(parameterSetEntry);

            PsSpecCmdletParameterDetails group = new PsSpecCmdletParameterDetails(parameter, parameters);

            PropertyInfo[] parameterProperties = parameter.GetType().GetProperties();
            PropertyInfo[] parameterSetEntryProperties = parameterSetEntry.GetType().GetProperties();
            PropertyInfo[] groupProperties = group.GetType().GetProperties();

            // The group should expose all properties but 4:
            // - The ID of the parameter set entry
            // - The project name of the parameter set entry
            // - The cmdlet name of the parameter set entry
            // - The parameter name of the parameter set entry
            Assert.AreEqual((parameterProperties.Length + (parameterSetEntryProperties.Length - 4)), groupProperties.Length);
        }
      }
}